/**
 * Implementacion de la clase NodeValidator
 */

#include "nodeValidator.hpp"
#include "../list/listIterator.hpp"
#include "../main/node.hpp"
#include "../config/config.hpp"
#include <stdlib.h>
#include <limits.h>

using namespace std;


void NodeValidator::validateMinAndMax(int xPosition,int yPosition){
    if (xPosition > this->xMax){
        this->xMax = xPosition;
    } else {
        if (xPosition < this->xMin) {
            this->xMin = xPosition;
        }
    }
    if (yPosition > this->yMax){
        this->yMax = yPosition;
    } else {
        if (yPosition < this->yMin){
            this->yMin = yPosition;
        }
    }
}

void NodeValidator::create(std::string &fileToParse, Logger *log, Graph *graph)
{
	this->setParser(fileToParse,log);
	this->logger = log;
	int number = atoi(Config::get("number_of_fields_expected_nodes").c_str());
	if(number > 0)
	{
		this->numberOfFieldsExpected = number;
		this->node.setSuccessStatus(4);
	}
	else
	{
		std::string detail = "Cantidad de campos esperados para la validacion de los nodos no tiene el formato esperado";
		this->logger->reportErrorMessage("NodeValidator","create",detail);
		this->node.setFailStatus(4);
	}
	this->graph = graph;
    this->xMax= INT_MIN;
    this->xMin= INT_MAX;
    this->yMax= INT_MIN;
    this->yMin= INT_MAX;
        
}

NodeValidator::NodeValidator(std::string &fileToParse, Logger *log, Graph *graph)
{
	this->create(fileToParse,log,graph);
}

NodeValidator::~NodeValidator()
{
	this->logger = 0;
	this->numberOfFieldsExpected = 0;
}

void NodeValidator::validateNumberOfFields(int lineCount, int fieldAmount)
{
	if(fieldAmount != this->numberOfFieldsExpected)
	{
		this->node.setFailStatus(4);
		std::string detail = "Cantidad de campos distinta a la esperada";
		this->logger->reportErrorMessage("NodeValidator","validateNumberOfFields", detail, lineCount);
	}
	else
		this->node.setSuccessStatus(4);
}
void NodeValidator::validateField(int lineCount, int fieldNumber, std::string field)
{
	std::string detail;
	if(fieldNumber == 1)
	{
		if((std::string::npos == field.find_first_of(','))&&(std::string::npos == field.find_first_of('.'))
			&&(field[0] != '0')&&(atoi(field.c_str()) == 0))
		{
			this->node.setNodeId(field);
		}
		else
		{
			detail = "Esperado un literal, se encontro un real";
			this->logger->reportErrorMessage("NodeValidator","validateField", detail,lineCount,fieldNumber);
			this->node.setFailStatus(fieldNumber);
		}
	}
	else
	{
		int numero = atoi(field.c_str());
		if((numero >= 0)||(numero <= 0))
		{
			if(fieldNumber == 2)
				this->node.setPositionX(numero);
			else
				this->node.setPositionY(numero);
		}
		//else if (numero == 0)
		//{
		//	detail = "Esperado un entero, se encontro un literal, o el real vale cero";
		//	this->logger->reportWarningMessage("NodeValidator","validateField", detail,lineCount,fieldNumber);
		//	this->node.setFailStatus(fieldNumber);
		//}
	}
}
void NodeValidator::validateElementAdding(int lineCount)
{
	bool success = true;
	std::string detail;

	if(this->node.getPositionXStatus() == 0)
		success = false;
	if(this->node.getPositionYStatus() == 0)
		success = false;
	if(this->node.getNodeIdStatus() == 0)
		success = false;
	if(this->node.getNumberOfFieldsStatus() == 0)
		success = false;

	if(success)
	{
		Node *nodeTemp = this->graph->getNode(this->node.getNodeId());
		if(nodeTemp == NULL)
		{
			Node *newNode = new Node(this->node.getNodeId(),this->node.getPositionX(),this->node.getPositionY());
			bool samePosition = false;

			List<Node> *lista = this->graph->getNodes();
			ListIterator<Node> it = lista->iterator();
			while((it.hasNext())&&(!samePosition))
			{
				if((it.next())->hasSamePosition(newNode))
					samePosition = true;
			}

			if(!samePosition)
			{
                validateMinAndMax(this->node.getPositionX(),this->node.getPositionY());
				this->graph->addNode(newNode);
				detail = "Nodo agregado, id: "; detail += this->node.getNodeId();
				this->logger->reportSuccessMessage("NodeValidator","validateGraphElementAdding",detail);
			}
			else
			{
				detail = "Nodo con mismas posiciones existente, nuevo nodo descartado, id: ";
				detail += this->node.getNodeId();
				this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail,lineCount);
			}
		}
		else
		{
			detail = "Nodo con Id existente descartado, id: "; detail += this->node.getNodeId();
			this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail,lineCount);
		}

	}
	else
	{
		detail = "Nodo descartado";
		this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail);
		this->node.clear();
	}

}

int NodeValidator::getXMax(){
    return this->xMax;
}

int NodeValidator::getYMax(){
    return this->yMax;
}

int NodeValidator::getXMin(){
    return this->xMin;
}
    
int NodeValidator::getYMin(){
    return this->yMin;
}
